
/* This is the server portion of program 3 */

#include "getKey.h"
#include "sgf.h"

void sig_child(int signo)
{
    pid_t pid;
    int state;
    while ((pid = waitpid(-1, &state, WNOHANG)) > 0)
	return;
}

void process_tran(int sockfd, char *key)
{

    struct authentication {
	char login[12];
	char password[7];
    };

    struct messages {
	int mssg_read;
	int mssg_unread;
    };

    struct authentication login_info;
    struct messages mssg;

    //populate student info structure
    bcopy("csc4360_6360",login_info.login,12);
    bcopy("sockets",login_info.password,7);

    //Populate total of unread and read messages 
    mssg.mssg_read = 0;
    mssg.mssg_unread = 9;

    //buffers for messages to be sent
    char dep_with_mssg[100], mailbox_mssg[75], email_mssg[50];
    char e_welcome_mssg[50], e_login_mssg[10], e_password_mssg[20], e_wrong_mssg[50], e_mssg_num_mssg[50], e_another_mssg[50], e_goodbye_mssg[50], e_mailbox_mssg[75], e_email_mssg[50];
    //receive buffers
    char recv_login[12], recv_password[7];
    char recv_buffer[50], dtext[50];
    //read messages array
    int read_array[10];

    //receive int
    int mssg_num;

    //receive char
    char y_n[2];

    //read counter
    int read_counter, i, j, flag, flag2;


    char welcome_mssg[] = "Welcome to Dr. Beyah's Patchy Email Server\n";
    memset(e_welcome_mssg, 0, 50);
    sgfe(key, welcome_mssg, e_welcome_mssg);
    char login_mssg[] = "Login: ";
    memset(e_login_mssg, 0, 10);
    sgfe(key, login_mssg, e_login_mssg);
    char password_mssg[] = "Password: ";
    memset(e_password_mssg, 0, 20);
    sgfe(key, password_mssg, e_password_mssg);
    char wrong_mssg[] = "Error: Invalid login or password!!!!!\n";
    memset(e_wrong_mssg, 0, 50);
    sgfe(key, wrong_mssg, e_wrong_mssg);
    char mssg_num_mssg[] = "Enter message number: ";
    memset(e_mssg_num_mssg, 0, 50);
    sgfe(key, mssg_num_mssg, e_mssg_num_mssg);
    char another_mssg[] = "Would you like to read another message? (y/n):";
    memset(e_another_mssg, 0, 50);
    sgfe(key, another_mssg, e_another_mssg);
    char goodbye_mssg[] = "Goodbye";
    memset(e_goodbye_mssg, 0, 50);
    sgfe(key, goodbye_mssg, e_goodbye_mssg);

    //clear read array
    bzero(read_array, sizeof(read_array));
    mssg_num = 0;

    //intialize read counter;
    read_counter = 0;

    //initialize flag
    flag = 0;


    // send welcome message
    Writen(sockfd, e_welcome_mssg, CTEXTLENGTH(strlen(welcome_mssg)));

    // send login message
    Writen(sockfd, e_login_mssg, CTEXTLENGTH(strlen(login_mssg)));

    // receive student login
    //Readn(sockfd, recv_login, 12);
    bzero(recv_buffer, sizeof(recv_buffer));
    bzero(recv_login, sizeof(recv_login));
    Readn(sockfd, recv_buffer, 16);
    sgfd(key, recv_buffer, CTEXTLENGTH(12), recv_login);

    // send password message
    Writen(sockfd, e_password_mssg, CTEXTLENGTH(strlen(e_password_mssg)));

    // receive student password
    bzero(recv_buffer, sizeof(recv_buffer));
    bzero(recv_password, sizeof(recv_password));
    Readn(sockfd, recv_buffer, 16);
    sgfd(key, recv_buffer, CTEXTLENGTH(7), recv_password);
    printf("%s, %s\n",recv_login, recv_password);
    //fflush(stdout);

    if ((bcmp(login_info.login,recv_login,12) == 0)  && (bcmp(login_info.password,recv_password,7) == 0))
    {

	do {

	    flag = 0;
	    flag2 = 0;
	    mssg_num = 0;	

	    sprintf(mailbox_mssg, "You have %d total messages - %d unread \n", (mssg.mssg_read+mssg.mssg_unread), mssg.mssg_unread);
	    //send mailbox message
	    bzero(e_mailbox_mssg, sizeof(e_mailbox_mssg));
	    sgfe(key, mailbox_mssg, e_mailbox_mssg);
	    Writen(sockfd, e_mailbox_mssg, CTEXTLENGTH(strlen(e_mailbox_mssg)));

	    // send enter message number message
	    Writen(sockfd, e_mssg_num_mssg, CTEXTLENGTH(strlen(e_mssg_num_mssg)));

	    // receive valid message number
	    bzero(recv_buffer, sizeof(recv_buffer));
	    bzero(dtext, sizeof(dtext));
	    Readn(sockfd, recv_buffer, 16);
	    sgfd(key, recv_buffer, CTEXTLENGTH(1), dtext);
	    printf("%s\n", dtext);
	    mssg_num = dtext[0] - '0';
	    //make sure number is in valid, exit if not
	    if ((mssg_num < 1) || (mssg_num > 9)) exit(0);


	    //store message number that was read in read array if it's not already in there
	    for(j = 0; j < 9; j++)
	    {
		if (mssg_num == read_array[j]) flag = 1;
		printf("\nif %d == %d flag = 1\n",mssg_num,read_array[j]);
	    }

	    if ((flag == 0) || (read_counter == 0))
	    {
		read_array[read_counter] = mssg_num;
		read_counter = read_counter + 1;
		mssg.mssg_unread = mssg.mssg_unread - 1;
		mssg.mssg_read = mssg.mssg_read + 1;
	    }

	    sprintf(email_mssg, "This is message %d.", mssg_num);
	    //send mailbox message
	    bzero(e_email_mssg, sizeof(e_email_mssg));
	    sgfe(key, email_mssg, e_email_mssg);
	    Writen(sockfd, e_email_mssg, CTEXTLENGTH(strlen(e_email_mssg)));

	    // send another message? message
	    Writen(sockfd, e_another_mssg, CTEXTLENGTH(strlen(e_another_mssg)));

	    // receive y = YES OR n = NO
	    bzero(recv_buffer, sizeof(recv_buffer));
	    bzero(dtext, sizeof(dtext));
	    Readn(sockfd, recv_buffer, CTEXTLENGTH(1));
	    sgfd(key, recv_buffer, CTEXTLENGTH(1), dtext);
	} while (dtext[0] == 'y');

	// send goodbye message
	Writen(sockfd, e_goodbye_mssg, CTEXTLENGTH(strlen(e_goodbye_mssg)));
    }
    else 
	Writen(sockfd, e_wrong_mssg, CTEXTLENGTH(strlen(e_wrong_mssg)));

} 

int main(int argc, char **argv)
{
    int			listenfd, connfd;
    pid_t			childpid;
    socklen_t		clilen;
    struct sockaddr_in	cliaddr, servaddr;

#define                 SERV_PORT        6225
    int KDC_port = 32000;
    char* key = getKey(KDC_SERV_IP, KDC_port);
    printf("the recv key is %s\n", key);

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    Listen(listenfd, 10);

    signal(SIGCHLD, sig_child);   /* cleans up zombie processes */

    for ( ; ; ) {
	clilen = sizeof(cliaddr);
	connfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
	printf("Connected to client from %s:%d, passing it to child to handle\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); 
	fflush(stdout);                 

	if ( (childpid = Fork()) == 0) {	/* child process */
	    Close(listenfd);	/* close listening socket */
	    process_tran(connfd, key);	/* process the request */
	    exit(0);
	}
	Close(connfd);			/* parent closes connected socket */
    }
    free(key);
}


